package com.example.app.sharescreen;

import android.content.Context;
import android.util.Log;

import com.example.app.Websocket.PeerConnectionObserver;

import org.webrtc.AudioSource;
import org.webrtc.AudioTrack;
import org.webrtc.DefaultVideoDecoderFactory;
import org.webrtc.DefaultVideoEncoderFactory;
import org.webrtc.EglBase;
import org.webrtc.IceCandidate;
import org.webrtc.MediaConstraints;
import org.webrtc.MediaStream;
import org.webrtc.PeerConnection;
import org.webrtc.PeerConnectionFactory;
import org.webrtc.RtpSender;
import org.webrtc.SdpObserver;
import org.webrtc.SessionDescription;
import org.webrtc.SurfaceTextureHelper;
import org.webrtc.SurfaceViewRenderer;
import org.webrtc.VideoCapturer;
import org.webrtc.VideoSource;
import org.webrtc.VideoTrack;

import java.util.ArrayList;
import java.util.List;

public class PeerConnectionManager {
    private static final String TAG = "PeerConnectionManager";
    
    private Context context;
    private EglBase eglBase;
    private PeerConnectionFactory peerConnectionFactory;
    private PeerConnection peerConnection;
    private VideoTrack localVideoTrack;
    private RtpSender videoSender;
    private VideoCapturer videoCapturer;
    private PeerConnectionCallback callback;
    
    public interface PeerConnectionCallback {
        void onIceCandidate(IceCandidate iceCandidate);
        void onAddStream(MediaStream mediaStream);
        void onRemoveStream(MediaStream mediaStream);
    }
    
    public PeerConnectionManager(Context context, EglBase eglBase, PeerConnectionCallback callback) {
        this.context = context;
        this.eglBase = eglBase;
        this.callback = callback;
        
        initPeerConnectionFactory();
    }
    
    private void initPeerConnectionFactory() {
        PeerConnectionFactory.InitializationOptions options =
                PeerConnectionFactory.InitializationOptions.builder(context)
                        .createInitializationOptions();
        PeerConnectionFactory.initialize(options);
        
        peerConnectionFactory = PeerConnectionFactory.builder()
                .setVideoEncoderFactory(new DefaultVideoEncoderFactory(
                        eglBase.getEglBaseContext(), true, true))
                .setVideoDecoderFactory(new DefaultVideoDecoderFactory(eglBase.getEglBaseContext()))
                .createPeerConnectionFactory();
    }
    
    public void createPeerConnection() {
        List<PeerConnection.IceServer> iceServers = new ArrayList<>();
        iceServers.add(PeerConnection.IceServer.builder(StaticData.STUNServerAddress).createIceServer());
        iceServers.add(PeerConnection.IceServer.builder(StaticData.TURNServerAddress)
                .setUsername(StaticData.TURNCustomerUserName)
                .setPassword(StaticData.TURNCustomerUserPassword)
                .createIceServer());
        
        PeerConnection.RTCConfiguration config = new PeerConnection.RTCConfiguration(iceServers);
        
        peerConnection = peerConnectionFactory.createPeerConnection(config, new PeerConnectionObserver() {
            @Override
            public void onIceCandidate(IceCandidate iceCandidate) {
                if (callback != null) {
                    callback.onIceCandidate(iceCandidate);
                }
            }
            
            @Override
            public void onAddStream(MediaStream mediaStream) {
                if (callback != null) {
                    callback.onAddStream(mediaStream);
                }
            }
            
            @Override
            public void onRemoveStream(MediaStream mediaStream) {
                if (callback != null) {
                    callback.onRemoveStream(mediaStream);
                }
            }
        });
    }
    
    public void setVideoCapturer(VideoCapturer capturer) {
        this.videoCapturer = capturer;
    }
    
    public void startLocalVideoCapture(SurfaceViewRenderer localVideoView) {
        if (videoCapturer == null) {
            Log.e(TAG, "Video capturer not set");
            return;
        }
        
        VideoSource videoSource = peerConnectionFactory.createVideoSource(false);
        if (localVideoTrack != null) {
            localVideoTrack.dispose();
        }
        
        videoCapturer.initialize(
                SurfaceTextureHelper.create("ScreenCaptureThread", eglBase.getEglBaseContext()),
                context,
                videoSource.getCapturerObserver());
        videoCapturer.startCapture(1280, 720, 15);
        
        localVideoTrack = peerConnectionFactory.createVideoTrack("screen", videoSource);
        localVideoTrack.addSink(localVideoView);
        
        AudioSource audioSource = peerConnectionFactory.createAudioSource(new MediaConstraints());
        AudioTrack localAudioTrack = peerConnectionFactory.createAudioTrack("audio", audioSource);
        
        if (peerConnection != null) {
            videoSender = peerConnection.addTrack(localVideoTrack);
            peerConnection.addTrack(localAudioTrack);
        }
    }
    
    public void createOffer(SdpObserver sdpObserver) {
        MediaConstraints constraints = new MediaConstraints();
        constraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveVideo", "true"));
        constraints.mandatory.add(new MediaConstraints.KeyValuePair("OfferToReceiveAudio", "true"));
        peerConnection.createOffer(sdpObserver, constraints);
    }
    
    public void createAnswer(SdpObserver sdpObserver) {
        peerConnection.createAnswer(sdpObserver, new MediaConstraints());
    }
    
    public void setLocalDescription(SdpObserver sdpObserver, SessionDescription sessionDescription) {
        peerConnection.setLocalDescription(sdpObserver, sessionDescription);
    }
    
    public void setRemoteDescription(SdpObserver sdpObserver, SessionDescription sessionDescription) {
        peerConnection.setRemoteDescription(sdpObserver, sessionDescription);
    }
    
    public void addIceCandidate(IceCandidate iceCandidate) {
        if (peerConnection != null) {
            peerConnection.addIceCandidate(iceCandidate);
        }
    }
    
    public void stopCapture() {
        if (videoCapturer != null) {
            try {
                videoCapturer.stopCapture();
            } catch (InterruptedException e) {
                Log.e(TAG, "Failed to stop capture: " + e.getMessage());
            }
        }
    }
    
    public void dispose() {
        if (videoCapturer != null) {
            try {
                videoCapturer.stopCapture();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            videoCapturer.dispose();
            videoCapturer = null;
        }
        
        if (localVideoTrack != null) {
            localVideoTrack.dispose();
            localVideoTrack = null;
        }
        
        if (peerConnection != null) {
            peerConnection.dispose();
            peerConnection = null;
        }
    }
    
    public VideoTrack getLocalVideoTrack() {
        return localVideoTrack;
    }
    public PeerConnection getPeerConnection() {
        return peerConnection;
    }
} 